#include "head_files.h"
#include "spiDebugger.h"

uint8_t spi1_tx_buffer[10];
uint8_t spi1_rx_buffer[10];
uint8_t spi1_tx_end_flag;
uint8_t spi1_rx_end_flag;

uint8_t spi1_transfer_in_progress;

float spi_table_test1 = 13.5;

//pc transfered buffer must has 5 element,fix 00 for no use
spiTable_t spiTable = 
{
	(void*)&(MOTOR_recv_s.mode),				Type_uint8_t,
	(void*)&(MOTOR_recv_s.Pos),					Type_float,
	(void*)&(MOTOR_recv_s.T),						Type_float,
	(void*)&(MOTOR_recv_s.W),						Type_float,
	(void*)&(MOTOR_recv_s.Temp),				Type_uint32_t,
	(void*)&(MOTOR_recv_s.footForce),		Type_float,
};


/***********************read table***************************/
/**
 * Read multiple data entries from the table based on commands in the SPI receive buffer
 * @param table Pointer to the spiTable_t structure
 * @param count Number of data entries to read
 * @return Number of successfully transmitted entries, negative on error
 */
int readMultipleFromTable(spiTable_t* table, uint8_t count)
{
    if (table == NULL || count == 0) {
        return -1; // Invalid parameters
    }
    
    uint8_t* tx_ptr = spi1_tx_buffer;  // Transmit buffer pointer
    uint16_t total_length = 0;
    int success_count = 0;
    
    // Process each requested index
    for (uint8_t i = 0; i < count; i++) {
				if(spi1_rx_buffer[i] == 0) continue;
			
        uint8_t index = spi1_rx_buffer[i] - 1;
        
        // Check index validity
        if (index >= 10) {
            continue; // Skip invalid index
        }
        
        spiTableElement_t* element = &table->spiTableElement[index];
        
        // Copy data to transmit buffer based on type
        switch (element->type) {
            case Type_uint8_t:
                *tx_ptr++ = *(uint8_t*)element->element;
                total_length += 1;
                break;
                
            case Type_uint16_t: {
                uint16_t value = *(uint16_t*)element->element;
                *tx_ptr++ = (value >> 8) & 0xFF;
                *tx_ptr++ = value & 0xFF;
                total_length += 2;
                break;
            }
                
            case Type_uint32_t: {
                uint32_t value = *(uint32_t*)element->element;
                *tx_ptr++ = (value >> 24) & 0xFF;
                *tx_ptr++ = (value >> 16) & 0xFF;
                *tx_ptr++ = (value >> 8) & 0xFF;
                *tx_ptr++ = value & 0xFF;
                total_length += 4;
                break;
            }
                
            case Type_float: {
                uint32_t* floatAsInt = (uint32_t*)element->element;
                *tx_ptr++ = (*floatAsInt >> 24) & 0xFF;
                *tx_ptr++ = (*floatAsInt >> 16) & 0xFF;
                *tx_ptr++ = (*floatAsInt >> 8) & 0xFF;
                *tx_ptr++ = *floatAsInt & 0xFF;
                total_length += 4;
                break;
            }
                
            default:
                continue; // Skip unsupported type
        }
        
        success_count++;
    }
    
    // Return error if no valid data
    if (success_count == 0) {
        return -2; // No valid data
    }
    
    // Calculate total transmission length
//    uint16_t total_length = (uint32_t)tx_ptr - (uint32_t)spi1_tx_buffer;
    
    // Transmit data via SPI
    HAL_StatusTypeDef status = HAL_SPI_Transmit_DMA(&hspi1, spi1_tx_buffer, total_length);
    
    return (status == HAL_OK) ? success_count : -3; // Return success count or error code
}



/**
 * Read data from the table and send it via SPI
 * @param table Pointer to the spiTable_t structure
 * @param index Index of the element to read (0-9)
 * @return 0 on success, error code on failure
 */
int readTableAndSend(spiTable_t* table, uint8_t index)
{
    if (table == NULL || index >= 10) {
        return -1; // Invalid parameter
    }
    
    spiTableElement_t* element = &table->spiTableElement[index];
    uint8_t length = 0;
    
    // Copy data to the transmit buffer based on its type
    switch (element->type) {
        case Type_uint8_t:
            spi1_tx_buffer[0] = *(uint8_t*)element->element;
            length = 1;
            break;
            
        case Type_uint16_t: {
            uint16_t value = *(uint16_t*)element->element;
            spi1_tx_buffer[0] = (value >> 8) & 0xFF;
            spi1_tx_buffer[1] = value & 0xFF;
            length = 2;
            break;
        }
            
        case Type_uint32_t: {
            uint32_t value = *(uint32_t*)element->element;
            spi1_tx_buffer[0] = (value >> 24) & 0xFF;
            spi1_tx_buffer[1] = (value >> 16) & 0xFF;
            spi1_tx_buffer[2] = (value >> 8) & 0xFF;
            spi1_tx_buffer[3] = value & 0xFF;
            length = 4;
            break;
        }
            
        case Type_float: {
            uint32_t* floatAsInt = (uint32_t*)element->element;
            spi1_tx_buffer[0] = (*floatAsInt >> 24) & 0xFF;
            spi1_tx_buffer[1] = (*floatAsInt >> 16) & 0xFF;
            spi1_tx_buffer[2] = (*floatAsInt >> 8) & 0xFF;
            spi1_tx_buffer[3] = *floatAsInt & 0xFF;
            length = 4;
            break;
        }
            
        default:
            return -2; // Unsupported type
    }
    
    // Transmit data via SPI
    return HAL_SPI_Transmit_DMA(&hspi1, spi1_tx_buffer, length);
}




/*********************Slave***********************/
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
	spi1_rx_end_flag = 1;
	spi1_transfer_in_progress = 1;
	//put into spi buffer
	spi1_tx_buffer[0] = 0x33;
	spi1_tx_buffer[1] = 0x27;
//	HAL_SPI_Transmit_DMA(&hspi1,spi1_tx_buffer,5);
	readMultipleFromTable(&spiTable,5);
}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
	spi1_tx_end_flag = 1;
	spi1_transfer_in_progress = 0;
	//wait for next receive
	HAL_SPI_Receive_DMA(&hspi1,spi1_rx_buffer,5);
}




/**********************clean************************/

void Clear_SPI_RX_Buffer(SPI_HandleTypeDef *hspi)
{
    uint8_t dummy;
    while (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) {
        
        dummy = hspi->Instance->DR;
        (void)dummy;
    }
}

void Clear_SPI_OVR_Flag(SPI_HandleTypeDef *hspi)
{
    if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_OVR)) {
        uint8_t dummy;
			
        dummy = hspi->Instance->DR;
        dummy = hspi->Instance->SR;
        (void)dummy;
    }
}

void Reset_SPI_DMA(SPI_HandleTypeDef *hspi)
{
    if (hspi->hdmatx != NULL) {
        HAL_DMA_Abort(hspi->hdmatx);
    }
    if (hspi->hdmarx != NULL) {
        HAL_DMA_Abort(hspi->hdmarx);
    }
    
    if (hspi->hdmatx != NULL) {
        hspi->hdmatx->State = HAL_DMA_STATE_READY;
    }
    if (hspi->hdmarx != NULL) {
        hspi->hdmarx->State = HAL_DMA_STATE_READY;
    }
}

void Reset_SPI_DMA_Buffers(SPI_HandleTypeDef *hspi)
{
    hspi->pTxBuffPtr = NULL;
    hspi->pRxBuffPtr = NULL;
    hspi->TxXferSize = 0;
    hspi->RxXferSize = 0;
    hspi->TxXferCount = 0;
    hspi->RxXferCount = 0;
}

void Clean_SPI_Buffer(SPI_HandleTypeDef *hspi)
{
    HAL_SPI_Abort(hspi);
    
    Clear_SPI_OVR_Flag(hspi);
    
    Clear_SPI_RX_Buffer(hspi);
    
    Reset_SPI_DMA(hspi);
    Reset_SPI_DMA_Buffers(hspi);
    
    hspi->State = HAL_SPI_STATE_READY;
}
